﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace Gonte
{
    public static class Finder<T>
    {
        /// <summary>
        /// Returns the first item that matches the matching delegate
        /// </summary>
        /// <param name="collection">The collection to search into</param>
        /// <param name="isMatch">The delegate that determines what item of the collection matches the search criteria</param>
        /// <param name="toCompare">The value to compare for a match</param>
        /// <returns>The item of the collection that matches the search criteria</returns>
        public static T Find(ICollection collection, IsMatch isMatch, object toCompare)
        {
            ExceptionThrower.ThrowWhenNull("collection", collection);
            ExceptionThrower.ThrowWhenNull("isMatch", isMatch);
            ExceptionThrower.ThrowWhenNull("toCompare", toCompare);

            IDictionary dictionary = collection as IDictionary;

            if (null != dictionary)
            {
                foreach (T item in dictionary.Values)
                {
                    if (isMatch(item, toCompare))
                    {
                        return item;
                    }
                }
            }
            else
            {
                foreach (T item in collection)
                {
                    if (isMatch(item, toCompare))
                    {
                        return item;
                    }
                }
            }

            return default(T);
        }

        /// <summary>
        /// Returns all the items that match the matching delegate
        /// </summary>
        /// <param name="collection">The collection to search into</param>
        /// <param name="isMatch">The delegate that determines what item of the collection matches the search criteria</param>
        /// <param name="toCompare">The value to compare for a match</param>
        /// <returns>The list of items of the collection that match the search criteria</returns>
        public static List<T> FindAll(ICollection collection, IsMatch isMatch, object toCompare)
        {
            List<T> foundList = new List<T>();

            ExceptionThrower.ThrowWhenNull("collection", collection);
            ExceptionThrower.ThrowWhenNull("isMatch", isMatch);
            ExceptionThrower.ThrowWhenNull("toCompare", toCompare);

            IDictionary dictionary = collection as IDictionary;

            if (null != dictionary)
            {
                foreach (T item in dictionary.Values)
                {
                    if (isMatch(item, toCompare))
                    {
                        foundList.Add(item);
                    }
                }
            }
            else
            {
                foreach (T item in collection)
                {
                    if (isMatch(item, toCompare))
                    {
                        foundList.Add(item);
                    }
                }
            }

            return foundList;
        }

        #region Delegates

        /// <summary>
        /// Determines what item of the collection matches the search criteria
        /// </summary>
        /// <param name="item">An existing item in the collection</param>
        /// <param name="toCompare">The value to compare for a match</param>
        /// <returns>True if toCompare matches the item, otherwise returns false</returns>
        public delegate bool IsMatch(T item, object toCompare);

        #endregion
    }
}
